package com.topisv.tms.service.send;

import java.util.Date;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.hibernate.ejb.criteria.predicate.ComparisonPredicate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.topisv.tms.entity.AreaGroup;
import com.topisv.tms.entity.CusStockMerge;
import com.topisv.tms.entity.Customers;
import com.topisv.tms.entity.LogisticsCompany;
import com.topisv.tms.entity.User;
import com.topisv.tms.entity.send.SendOut;
import com.topisv.tms.mybatis.SqlMapDao;
import com.topisv.tms.repository.AreaGroupDao;
import com.topisv.tms.repository.CustomersDao;
import com.topisv.tms.repository.send.SendOutDao;
import com.topisv.tms.service.AreaGroupService;
import com.topisv.tms.service.CustomersService;
import com.topisv.tms.service.LogisticsCompanyService;
import com.topisv.tms.service.UserService;
import com.topisv.tms.service.account.ShiroDbRealm.ShiroUser;
import com.topisv.tms.utils.enums.StatusEnums;

@Component
public class SendOutService {
	protected Logger logger = LoggerFactory.getLogger(getClass());
	@Autowired
	private SendOutDao sendOutDao;
	@Autowired
	private CustomersDao customersDao;
	@Autowired
	private AreaGroupDao areagroupDao;
	@Autowired 
	private UserService userService;
	@Autowired
	private CustomersService customersService;
	@Autowired
	private AreaGroupService areaGroupService;
	@Autowired
	private LogisticsCompanyService logisticsCompanyService;
	@PersistenceContext
    private EntityManager em;

	
	
	@Transactional(readOnly = false)
	public void save(SendOut sendOut){
		sendOutDao.save(sendOut);
	}
	
	@Transactional(readOnly = true)
	public SendOut findByLogisticNumber(String logisticNumber){
		return sendOutDao.findByLogisticNumber(logisticNumber);
	}
	
	/**
	 * 根据流水号查询快递交接明细
	 * 
	 *
	 * @param sendCode
	 * @return [参数说明]
	 * @author <a href=mailto:zhangweize@nryuncang.com>zhangweize</a>
	 * @version 1.0.0
	 */
	@Transactional(readOnly = true)
	public List<SendOut> findBySendCode(String sendCode) throws Exception{
		 List<SendOut> list = sendOutDao.findListBySendOut(sendCode);
		 if (list == null || list.isEmpty()){
			 throw new RuntimeException("该装车流水号不存在,请检查!");
		 }
		 
		this.setDetail(list.get(0));	
		return list;
	}
	@Transactional(readOnly = false)
	public void updateSendOutPrintTime(String sendCode) throws Exception{
		Date now = new Date();
		 sendOutDao.updateSendOutPrintTime(now, sendCode);
	}
	
	
	@Transactional(readOnly = true)
	public List<SendOut> getAllSendOut(){
		List<SendOut> list = (List<SendOut>)sendOutDao.findAll();
		for (SendOut sendOut : list) {
	    	this.setDetail(sendOut);	
	    }
		return list;
	}
	
	@Transactional(readOnly = true)
	public List<SendOut> getTodaySendOut(String warehouseCode,java.sql.Date start,java.sql.Date end){
		List<SendOut> list = sendOutDao.findTodayLogistic(warehouseCode,start,end);
		for(SendOut sendOut:list){
			this.setDetail(sendOut);
		}
		return list;
	}
	
	/**
	 * 分页查询
	 * @param param
	 * @return
	 */
	public Page<SendOut> loadPageByParam(Map<String, Object> param,int pageNumber, int pageSize) {
		Sort sort = new Sort(Sort.Direction.ASC,"logisticNumber") ; 
	    PageRequest pageRequest = new PageRequest(pageNumber-1, pageSize, sort);
	    Specification<SendOut> spec =this.getWhereClause(param);
	    
	    Page<SendOut> page = this.sendOutDao.findAll(spec, pageRequest);
	    List<SendOut> sendOutList=page.getContent();
	    for (SendOut sendOut : sendOutList) {
	    	this.setDetail(sendOut);	
	    }
	    return page;
	}
	
	/**
	 * 查询条件封装
	 * @param param
	 * @return
	 */
	private Specification<SendOut> getWhereClause(final Map<String, Object> param) {
		
		return new Specification<SendOut>(){
			
			@Override
		    public Predicate toPredicate(Root<SendOut> r, CriteriaQuery<?> q, CriteriaBuilder cb) {
		      Predicate pre = cb.conjunction();
		      ShiroUser user = (ShiroUser) SecurityUtils.getSubject().getPrincipal();
		      try {
		    	  String expressCompany=(String) param.get("expressCompany");
		    	  if(StringUtils.isNotBlank(expressCompany)){
						pre.getExpressions().add(cb.equal(r.<String>get("logisticCompany"), expressCompany));
				  }
			      
		    	  Object fromDate=  param.get("fromDate");
			      if (fromDate != null) {
			        pre.getExpressions().add(cb.greaterThanOrEqualTo(r.<Date>get("sendTime"), (Date)fromDate));
			      }
			      
			      //结束时间
			      Object toDate= param.get("toDate");
			      if (toDate != null) {
			        pre.getExpressions().add(cb.lessThanOrEqualTo(r.<Date>get("sendTime"), (Date)toDate));
			      }
			      
			      String expressNo=(String) param.get("expressNo");
			      if(StringUtils.isNotEmpty(expressNo)){
						pre.getExpressions().add(cb.equal(r.get("logisticNumber"),expressNo));
				  }
			      
			  	  //bug530 by zhangweize
			      //装车流水号
			      String sendCode=(String) param.get("sendCode");
			      if(StringUtils.isNotEmpty(sendCode)){
						pre.getExpressions().add(cb.equal(r.get("sendCode"),sendCode));
				  }
			      
			      String warehouse = (String) param.get("warehouse");
		    	  if(StringUtils.isNotBlank(warehouse)){
						pre.getExpressions().add(cb.equal(r.<String>get("warehouseCode"), warehouse));
				  }else{
					  List<AreaGroup> warehouseList = null;
					  if (StatusEnums.user_type_customer.getStatus().equals(user.userType)) {
							warehouseList = areaGroupService.loadAreaGroupByAuthority(user, user.customerCode);
						} else if (StatusEnums.user_type_paiu.getStatus().equals(user.userType)) {
					       warehouseList = areaGroupService.findByAreaGroups(user.areagroups);
					  }
					  
					  ComparisonPredicate[] areagroupArray  = new ComparisonPredicate[warehouseList.size()];
					  int j = 0;
					  for(AreaGroup areaGroup:warehouseList){
						  areagroupArray[j] = (ComparisonPredicate) cb.equal(r.get("warehouseCode"), areaGroup.getGroupCode());
						  j++;
					  } 
					  pre.getExpressions().add(cb.or(areagroupArray));
				  }
				}
			  catch (Exception e) {
				  e.printStackTrace();
			  }
		      
		      return pre;
		    }
		  };
       }
	
	/**
	 * 设置快递交接详细数据
	 * @param SendOutList
	 */
	private void setDetail(SendOut sendOut){
		//商家
		String customerCode=sendOut.getCustomerCode();
		Customers customer=this.customersDao.findByCustomerCode(customerCode);
		sendOut.setCustomer(customer);
		
		//仓库
		String warehouseCode=sendOut.getWarehouseCode();
		AreaGroup warehouse=this.areagroupDao.findByGroupCode(warehouseCode);
		sendOut.setWarehouse(warehouse);
		
		//操作人员
		Long senderId=(long) sendOut.getCreatedBy();
		User sender = this.userService.findOne(senderId);
		sendOut.setSender(sender);
		
		//快递公司
		String logisticsCode = sendOut.getLogisticCompany();
		LogisticsCompany company = this.logisticsCompanyService.getLogisticsCompanyByCode(logisticsCode);
		sendOut.setCompany(company);
	}
	
	public List<SendOut> findSendOut(Map<String, Object> param){
		Specification<SendOut> spec = getWhereClause(param);
		List<SendOut> list = sendOutDao.findAll(spec);
		for (SendOut sendOut : list) {
	    	this.setDetail(sendOut);	
	    }
		return list;
	}

	/**
	 * 查找快递交接清单（新） add 2016-06-12  by lianghe.yuan
	 * 
	 * @param param
	 * @return 数据集合
	 */
	@SuppressWarnings("unchecked")
    public List<Object[]> findSendOutNew(Map<String, Object> param){
        //构建SQL
	    StringBuffer sql = new StringBuffer("SELECT ");

	    sql.append("a.send_time 交接时间, ").append("b.company_name 快递公司, ")
    	    .append("a.logistic_number 快递单号, ").append("d.group_name 仓库, ")
    	    .append("c.realname 交接人 ");
	    
	    sql.append(" FROM tt_send a ")
	        .append(" LEFT JOIN logistics_company b ON a.logistic_company=b.company_code ")
	        .append(" LEFT JOIN tbl_user c ON a.created_by=c.id ")
	        .append(" LEFT JOIN pms_areagroup d ON a.warehouse_code=d.group_code " );
	    
	    sql.append(" WHERE 1=1 ");
	    
	    String expressCompany        = (String) param.get("expressCompany");
	    String expressNo                 = (String) param.get("expressNo");
        String warehouse                 = (String) param.get("warehouse");
        List<String> warehouseList   = (List<String>) param.get("warehouseList");
        String fromDate                   = (String) param.get("fromDate");
        String toDate                       = (String) param.get("toDate");
	    
	    if (StringUtils.isNotBlank(expressCompany))    sql.append(" AND a.logistic_company = ? ");
	    if (StringUtils.isNotBlank(expressNo))             sql.append(" AND a.logistic_number = ? ");
	    if (StringUtils.isNotBlank(fromDate))               sql.append(" AND a.send_time >= ? ");
	    if (StringUtils.isNotBlank(toDate))                   sql.append(" AND a.send_time <= ? ");
	    
	    if (StringUtils.isNotBlank(warehouse)) {
	        sql.append(" AND a.warehouse_code = ? ");
	    } else {
	        sql.append(" AND a.warehouse_code in (:warehouseList) ");
	    }
	    

	    //构建Query， 参数
	    Query query = em.createNativeQuery(sql.toString());
	    
	    int i = 1;
	    if (StringUtils.isNotBlank(expressCompany))    query.setParameter(i++, expressCompany);
	    if (StringUtils.isNotBlank(expressNo))             query.setParameter(i++, expressNo);
	    if (StringUtils.isNotBlank(fromDate))               query.setParameter(i++, fromDate);
	    if (StringUtils.isNotBlank(toDate))                   query.setParameter(i++, toDate);
	    
	    if (StringUtils.isNotBlank(warehouse)) {
	        query.setParameter(i++, warehouse);
	    } else {
	        ((org.hibernate.ejb.HibernateQuery) query).getHibernateQuery().setParameterList("warehouseList", warehouseList);
	    }
	    
	    return query.getResultList();
	}

}
